package com.chongchong.flow.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.jimmyshi.beanquery.BeanQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chongchong.common.constant.ErrorCodeEnum;
import com.chongchong.common.tool.CommonUtil;
import com.chongchong.common.validator.UpdateGroup;
import com.chongchong.core.boot.ctrl.SysController;
import com.chongchong.core.mp.object.MyModelUtil;
import com.chongchong.core.mp.support.Condition;
import com.chongchong.core.mp.support.Query;
import com.chongchong.core.secure.SysUser;
import com.chongchong.core.tool.api.R;
import com.chongchong.flow.dto.FlowCategoryDto;
import com.chongchong.flow.entity.FlowCategory;
import com.chongchong.flow.entity.FlowEntry;
import com.chongchong.flow.entity.constant.FlowEntryStatus;
import com.chongchong.flow.service.IFlowCategoryService;
import com.chongchong.flow.service.IFlowEntryService;
import com.chongchong.flow.vo.FlowCategoryVo;
import com.chongchong.flow.wrapper.FlowCategoryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.groups.Default;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * 工作流分类操作控制器类。
 *
 * @author Jerry
 * @date 2021-06-06
 */
@Api(tags = "工作流分类操作接口")
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/flowcategory")
public class FlowCategoryController extends SysController {
	@Autowired
    private IFlowCategoryService flowCategoryService;
	@Autowired
    private IFlowEntryService flowEntryService;

    /**
     * 新增FlowCategory数据。
     *
     * @param flowCategoryDto 新增对象。
     * @return 应答结果对象，包含新增对象主键Id。
     */
    @ApiOperationSupport(ignoreParameters = {"flowCategoryDto.categoryId"})
    @PostMapping("/add")
    public R<Long> add(@RequestBody FlowCategoryDto flowCategoryDto) {
        String errorMessage = CommonUtil.getModelValidationError(flowCategoryDto);
        if (errorMessage != null) {
            return R.fail(errorMessage);
        }
        FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class);
        flowCategory = flowCategoryService.saveNew(flowCategory);
        return R.data(flowCategory.getCategoryId());
    }

    /**
     * 更新FlowCategory数据。
     *
     * @param flowCategoryDto 更新对象。
     * @return 应答结果对象。
     */
    @PostMapping("/update")
    public R<Void> update(@RequestBody FlowCategoryDto flowCategoryDto) {
        String errorMessage = CommonUtil.getModelValidationError(flowCategoryDto, Default.class, UpdateGroup.class);
        if (errorMessage != null) {
            return R.fail(errorMessage);
        }
        FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class);
        FlowCategory originalFlowCategory = flowCategoryService.getById(flowCategory.getCategoryId());
        if (originalFlowCategory == null) {
            errorMessage = "数据验证失败，当前流程分类并不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        if (!StrUtil.equals(flowCategory.getCode(), originalFlowCategory.getCode())) {
            FlowEntry filter = new FlowEntry();
            filter.setCategoryId(flowCategory.getCategoryId());
            filter.setStatus(FlowEntryStatus.PUBLISHED);
            List<FlowEntry> flowEntryList = flowEntryService.getFlowEntryList(filter, null); // "update_time"
            if (CollUtil.isNotEmpty(flowEntryList)) {
                errorMessage = "数据验证失败，当前流程分类存在已经发布的流程数据，因此分类标识不能修改！";
                return R.fail(errorMessage);
            }
        }
        if (!flowCategoryService.update(flowCategory, originalFlowCategory)) {
            return R.fail(ErrorCodeEnum.DATA_NOT_EXIST.getErrorMessage());
        }
        return R.success("更新成功");
    }

    /**
     * 删除FlowCategory数据。
     *
     * @param categoryId 删除对象主键Id。
     * @return 应答结果对象。
     */
    @PostMapping("/delete")
    public R<Void> delete(@RequestBody Long categoryId) {
        String errorMessage;
        if (CommonUtil.existBlankArgument(categoryId)) {
            return R.fail(ErrorCodeEnum.ARGUMENT_NULL_EXIST.getErrorMessage());
        }
        // 验证关联Id的数据合法性
        FlowCategory originalFlowCategory = flowCategoryService.getById(categoryId);
        if (originalFlowCategory == null) {
            errorMessage = "数据验证失败，当前流程分类并不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        FlowEntry filter = new FlowEntry();
        filter.setCategoryId(categoryId);
        List<FlowEntry> flowEntryList = flowEntryService.getFlowEntryList(filter, null); // "update_time"
        if (CollUtil.isNotEmpty(flowEntryList)) {
            errorMessage = "数据验证失败，请先删除当前流程分类关联的流程数据！";
            return R.fail(errorMessage);
        }
        if (!flowCategoryService.remove(categoryId)) {
            errorMessage = "数据操作失败，删除的对象不存在，请刷新后重试！";
            return R.fail(errorMessage);
        }
        return R.success("删除成功");
    }

    /**
     * 列出符合过滤条件的FlowCategory列表。
     *
     * @return 应答结果对象，包含查询结果集。
     */
    @GetMapping("/list")
    public R<IPage<FlowCategoryVo>> list(FlowCategory flowCategory, Query query) {
		IPage<FlowCategory> pages = flowCategoryService.page(Condition.getPage(query), Condition.getQueryWrapper(flowCategory));
		return R.data(FlowCategoryWrapper.build().pageVO(pages));
    }

	/**
	 * 列出符合过滤条件的FlowCategory列表。
	 *
	 * @return 应答结果对象，包含查询结果集。
	 */
//	@GetMapping("/listNoPage")
//	public R<List<FlowCategoryVo>> listNoPage(FlowCategory flowCategory) {
//		List<FlowCategory> list = flowCategoryService.list(Condition.getQueryWrapper(flowCategory));
//		return R.data(FlowCategoryWrapper.build().listVO(list));
//	}

	/**
	 * 详情
	 */
	@GetMapping("/view")
	@ApiOperation(value = "详情", notes = "传入categoryId")
	public R<FlowCategoryVo> view(@RequestParam Long categoryId) {
		FlowCategory flowCategory = new FlowCategory();
		flowCategory.setCategoryId(categoryId);
		FlowCategory detail = flowCategoryService.getOne(Condition.getQueryWrapper(flowCategory));
		if (detail == null) {
			return R.fail(ErrorCodeEnum.DATA_NOT_EXIST.getErrorMessage());
		}
		return R.data(FlowCategoryWrapper.build().entityVO(detail));
	}

    /**
     * 查看指定FlowCategory对象详情。
     *
     * @return 应答结果对象，包含对象详情。
     */
    @GetMapping("/listNoPage")
    public R<List<FlowCategoryVo>> listNoPage(@ApiIgnore @RequestParam Map<String, Object> flowCategory, SysUser sysUser) {
		QueryWrapper<FlowCategory> queryWrapper = Condition.getQueryWrapper(flowCategory, FlowCategory.class);
		List<FlowCategory> list = flowCategoryService.list(queryWrapper);
		return R.data(FlowCategoryWrapper.build().listVO(list));
    }

    /**
     * 以字典形式返回全部FlowCategory数据集合。字典的键值为[categoryId, name]。
     * 白名单接口，登录用户均可访问。
     *
     * @param filter 过滤对象。
     * @return 应答结果对象，包含的数据为 List<Map<String, String>>，map中包含两条记录，key的值分别是id和name，value对应具体数据。
     */
    @GetMapping("/listDict")
    public R<List<Map<String, Object>>> listDict(FlowCategory filter) {
        List<FlowCategory> resultList = flowCategoryService.getFlowCategoryList(filter, null);
        return R.data(BeanQuery.select("categoryId as id", "name as name").executeFrom(resultList));
    }

    /**
     * 根据字典Id集合，获取查询后的字典数据。
     *
     * @param dictIds 字典Id集合。
     * @return 应答结果对象，包含字典形式的数据集合。
     */
    @PostMapping("/listDictByIds")
    public R<List<Map<String, Object>>> listDictByIds(@RequestBody List<Long> dictIds) {
        List<FlowCategory> resultList = flowCategoryService.listByIds(new HashSet<>(dictIds));
        return R.data(BeanQuery.select(
                "categoryId as id", "name as name").executeFrom(resultList));
    }
}
